﻿using System;
using System.Web;
using System.Data;

using LTJ.Common;
using LTJ.Config;
using LTJ.Data;
using LTJ.Common.Generic;
using LTJ.Entity;

namespace LTJ.FrameWork
{
    /// <summary>
    /// 在线用户操作类
    /// </summary>
    public class OnlineUsers
    {
        private static object SynObject = new object();

        /// <summary>
        /// 复位在线表, 如果系统未重启, 仅是应用程序重新启动, 则不会重新创建
        /// </summary>
        /// <returns></returns>
        public static int ResetOnlineList()
        {
            try
            {
                // 取得在线表最后一条记录的tickcount字段 (因为本功能不要求特别精确)
                //int tickcount = DatabaseProvider.GetInstance().GetLastTickCount();
                // 如果距离现在系统运行时间小于10分钟
                if (System.Environment.TickCount < 600000 && System.Environment.TickCount > 0)
                    return LTJ.Data.DataProvider.OnlineUsers.CreateOnlineTable();

                return -1;
            }
            catch
            {
                try
                {
                    return LTJ.Data.DataProvider.OnlineUsers.CreateOnlineTable();
                }
                catch
                {
                    return -1;
                }
            }

        }

        /// <summary>
        /// 用户在线信息维护。判断当前用户的身份(会员还是游客),是否在在线列表中存在,如果存在则更新会员的当前动,不存在则建立.
        /// </summary>
        /// <param name="passwordkey">passwordkey</param>
        /// <param name="timeout">在线超时时间</param>
        /// <param name="passwd">用户密码</param>
        public static OnlineUserInfo UpdateInfo(string passwordkey, int timeout, int uid, string passwd)
        {
            lock (SynObject)
            {
                OnlineUserInfo onlineuser = new OnlineUserInfo();
                string ip = SASRequest.GetIP();
                int userid = TypeConverter.StrToInt(FrameWorkUtil.GetCookie("userid"), uid);
                string password = (Utils.StrIsNullOrEmpty(passwd) ? FrameWorkUtil.GetCookiePassword(passwordkey) : FrameWorkUtil.GetCookiePassword(passwd, passwordkey));

                // 如果密码非Base64编码字符串则怀疑被非法篡改, 直接置身份为游客
                if (password.Length == 0 || !Utils.IsBase64String(password))
                    userid = -1;

                if (userid != -1)
                {
                    onlineuser = GetOnlineUser(userid, password);

                    if (onlineuser != null)
                    {
                        if (onlineuser.olip != ip)
                        {
                            UpdateIP(onlineuser.id, ip);
                            onlineuser.olip = ip;
                            return onlineuser;
                        }
                    }
                    else
                    {
                        // 判断密码是否正确
                        userid = Users.CheckPassword(userid, password, false);
                        if (userid != -1)
                        {
                            LTJ.Data.DataProvider.OnlineUsers.DeleteRowsByIP(ip);
                            //CheckIp(ip);
                            return CreateUser(userid, timeout);
                        }
                        else
                        {
                            //CheckIp(ip);
                            // 如密码错误则在在线表中创建游客
                            onlineuser = GetOnlineUserByIP(-1, ip);
                            if (onlineuser == null)
                                return CreateGuestUser(timeout);
                        }
                    }
                }
                else
                {
                    onlineuser = GetOnlineUserByIP(-1, ip);

                    if (onlineuser == null)
                        return CreateGuestUser(timeout);
                }

                onlineuser.lastupdate = Utils.GetDateTime();
                return onlineuser;
            }
        }

        #region 查看指定的某一用户的详细信息

        public static OnlineUserInfo GetOnlineUser(int olid)
        {
            return LTJ.Data.DataProvider.OnlineUsers.GetOnlineUser(olid);
        }

        /// <summary>
        /// 获得指定用户的详细信息
        /// </summary>
        /// <param name="userid">在线用户ID</param>
        /// <param name="password">用户密码</param>
        /// <returns>用户的详细信息</returns>
        private static OnlineUserInfo GetOnlineUser(int userid, string password)
        {
            return LTJ.Data.DataProvider.OnlineUsers.GetOnlineUser(userid, password);
        }

        /// <summary>
        /// 获得指定用户的详细信息
        /// </summary>
        /// <returns>用户的详细信息</returns>
        private static OnlineUserInfo GetOnlineUserByIP(int userid, string ip)
        {
            return LTJ.Data.DataProvider.OnlineUsers.GetOnlineUserByIP(userid, ip);
        }

        /// <summary>
        /// 检查在线用户验证码是否有效
        /// </summary>
        /// <param name="olid">在组用户ID</param>
        /// <param name="verifycode">验证码</param>
        /// <returns>在组用户ID</returns>
        public static bool CheckUserVerifyCode(int olid, string verifycode)
        {
            return LTJ.Data.DataProvider.OnlineUsers.CheckUserVerifyCode(olid, verifycode, FrameWorkUtil.CreateAuthStr(5, false));
        }

        #endregion

        #region 添加新的在线用户


        /// <summary>
        /// Cookie中没有用户ID或则存的的用户ID无效时在在线表中增加一个游客.
        /// </summary>
        public static OnlineUserInfo CreateGuestUser(int timeout)
        {
            OnlineUserInfo onlineuserinfo = new OnlineUserInfo();

            onlineuserinfo.uid = -1;
            onlineuserinfo.lname = "游客";
            onlineuserinfo.rname = "游客";
            onlineuserinfo.password = "";
            onlineuserinfo.groupid = 7;
            //onlineuserinfo.uimg = GetGroupImg(7);
            onlineuserinfo.olip = SASRequest.GetIP();
            onlineuserinfo.lastupdate = "1900-1-1 00:00:00";
            onlineuserinfo.verifycode = FrameWorkUtil.CreateAuthStr(5, false);
            onlineuserinfo.id = LTJ.Data.DataProvider.OnlineUsers.CreateOnlineUserInfo(onlineuserinfo, timeout);

            return onlineuserinfo;
        }


        /// <summary>
        /// 增加一个会员信息到在线列表中。用户login.aspx或在线用户信息超时,但用户仍在线的情况下重新生成用户在线列表
        /// </summary>
        /// <param name="uid"></param>
        private static OnlineUserInfo CreateUser(int uid, int timeout)
        {
            OnlineUserInfo onlineuserinfo = new OnlineUserInfo();
            if (uid > 0)
            {
                UserInfo ui = Users.GetUser(uid);
                if (ui != null)
                {
                    onlineuserinfo.uid = uid;
                    onlineuserinfo.lname = ui.lname.Trim();
                    onlineuserinfo.rname = ui.rname.Trim();
                    onlineuserinfo.password = ui.pass.Trim();
                    onlineuserinfo.groupid = short.Parse(ui.gid.ToString());
                    //onlineuserinfo.uimg = GetGroupImg(short.Parse(ui.Ps_ug_id.ToString()));
                    onlineuserinfo.olip = SASRequest.GetIP();
                    onlineuserinfo.lastupdate = "1900-1-1 00:00:00";
                    onlineuserinfo.verifycode = FrameWorkUtil.CreateAuthStr(5, false);
                    onlineuserinfo.id = LTJ.Data.DataProvider.OnlineUsers.CreateOnlineUserInfo(onlineuserinfo, timeout);

                    LTJ.Data.DataProvider.OnlineUsers.SetUserOnlineState(uid, 1, onlineuserinfo.verifycode);

                    HttpCookie cookie = HttpContext.Current.Request.Cookies["dyj"];
                    if (cookie != null)
                    {
                        if (HttpContext.Current.Request.Cookies["dyj"]["expires"] != null)
                        {
                            int expires = TypeConverter.StrToInt(HttpContext.Current.Request.Cookies["dyj"]["expires"].ToString(), 0);
                            if (expires > 0)
                            {
                                cookie.Expires = DateTime.Now.AddMinutes(TypeConverter.StrToInt(HttpContext.Current.Request.Cookies["dyj"]["expires"].ToString(), 0));
                            }
                        }
                    }

                    string cookieDomain = GeneralConfigs.GetConfig().CookieDomain.Trim();
                    if (!Utils.StrIsNullOrEmpty(cookieDomain) && HttpContext.Current.Request.Url.Host.IndexOf(cookieDomain) > -1 && FrameWorkUtil.IsValidDomain(HttpContext.Current.Request.Url.Host))
                        cookie.Domain = cookieDomain;
                    HttpContext.Current.Response.AppendCookie(cookie);
                }
                else
                {
                    onlineuserinfo = CreateGuestUser(timeout);
                }
            }
            else
            {
                onlineuserinfo = CreateGuestUser(timeout);
            }

            return onlineuserinfo;
        }

        /// <summary>
        /// 检查ip地址是否合法
        /// </summary>
        /// <param name="ip"></param>
        private static void CheckIp(string ip)
        {
            //string errmsg = "";
            ////判断IP地址是否合法,需要重构
            //LTJ.Common.Generic.List<IpInfo> list = Caches.GetBannedIpList();

            //foreach (IpInfo ipinfo in list)
            //{
            //    if (ip == (string.Format("{0}.{1}.{2}.{3}", ipinfo.Ip1, ipinfo.Ip2, ipinfo.Ip3, ipinfo.Ip4)))
            //    {
            //        errmsg = "您的ip被封,于" + ipinfo.Expiration + "后解禁";
            //        break;
            //    }

            //    if (ipinfo.Ip4.ToString() == "*")
            //    {
            //        if ((TypeConverter.StrToInt(ip.Split('.')[0], -1) == ipinfo.Ip1) && (TypeConverter.StrToInt(ip.Split('.')[1], -1) == ipinfo.Ip2) && (TypeConverter.StrToInt(ip.Split('.')[2], -1) == ipinfo.Ip3))
            //        {
            //            errmsg = "您所在的ip段被封,于" + ipinfo.Expiration + "后解禁";
            //            break;
            //        }
            //    }
            //}

            //if (errmsg != string.Empty)
            //    HttpContext.Current.Response.Redirect(BaseConfigs.GetSitePath + "tools/error.htm?templatepath=default&msg=" + Utils.UrlEncode(errmsg));
        }

        /// <summary>
        /// 用户在线信息维护。判断当前用户的身份(会员还是游客),是否在在线列表中存在,如果存在则更新会员的当前动,不存在则建立.
        /// </summary>
        /// <param name="passwordkey">用户密码</param>
        /// <param name="timeout">在线超时时间</param>
        public static OnlineUserInfo UpdateInfo(string passwordkey, int timeout)
        {
            return UpdateInfo(passwordkey, timeout, -1, "");
        }

        #endregion

        #region 在组用户信息更新

        /// <summary>
        /// 更新用户IP地址
        /// </summary>
        /// <param name="olid">在线id</param>
        /// <param name="ip">ip地址</param>
        public static void UpdateIP(int olid, string ip)
        {
            LTJ.Data.DataProvider.OnlineUsers.UpdateIP(olid, ip);
        }

        #endregion

        /// <summary>
        /// 删除在线表中指定在线id的行
        /// </summary>
        /// <param name="olid">在线id</param>
        /// <returns></returns>
        public static int DeleteRows(int olid)
        {
            return LTJ.Data.DataProvider.OnlineUsers.DeleteRows(olid);
        }

        /// <summary>
        /// 更新在线时间
        /// </summary>
        /// <param name="oltimespan">在线时间间隔</param>
        /// <param name="uid">当前用户id</param>
        public static void UpdateOnlineTime(int oltimespan, int uid)
        {
            //为0代表关闭统计功能
            if (oltimespan != 0)
            {
                if (Utils.StrIsNullOrEmpty(Utils.GetCookie("lastactivity", "onlinetime")))
                    Utils.WriteCookie("lastactivity", "onlinetime", System.Environment.TickCount.ToString());

                if ((System.Environment.TickCount - TypeConverter.StrToInt(Utils.GetCookie("lastactivity", "onlinetime"), System.Environment.TickCount) >= oltimespan * 60 * 1000))
                {
                    LTJ.Data.DataProvider.OnlineUsers.UpdateOnlineTime(oltimespan, uid);
                    Utils.WriteCookie("lastactivity", "onlinetime", System.Environment.TickCount.ToString());

                    //判断是否同步oltime (登录后的第一次onlinetime更新的时候或者在线超过1小时)
                    if (Utils.StrIsNullOrEmpty(Utils.GetCookie("lastactivity", "oltime")) || (System.Environment.TickCount - TypeConverter.StrToInt(Utils.GetCookie("lastactivity", "onlinetime"), System.Environment.TickCount) >= 60 * 60 * 1000))
                    {
                        LTJ.Data.DataProvider.OnlineUsers.SynchronizeOnlineTime(uid);
                        Utils.WriteCookie("lastactivity", "oltime", System.Environment.TickCount.ToString());
                    }
                }
            }
        }

        /// <summary>
        /// 更新在线操作
        /// </summary>
        /// <param name="olid"></param>
        /// <param name="actid"></param>
        public static void UpdateAction(int olid, int actid)
        {
            LTJ.Data.DataProvider.OnlineUsers.UpdateAction(olid, actid);
        }

        /// <summary>
        /// 删除指定在线用户信息
        /// </summary>
        /// <param name="uid"></param>
        public static void DeleteRowsByUid(int uid)
        {
            LTJ.Data.DataProvider.OnlineUsers.DeleteRowsByUid(uid);
        }

    }
}
